﻿using System;
using System.Collections.Generic;
using Server.Mobiles;
using Server.Commands;
using Server.Targeting;
using Server.Gumps;
using Server.Network;

namespace Server.Engines.GroupSystem
{
    public class GruppoBase
    {
        const int m_maxPartecipanti = 8; 
        private int m_numPartecipanti;
        private List<PlayerMobile> m_Partecipanti;
        private PlayerMobile m_Fondatore;

        public static void Initialize()
        {
            CommandSystem.Register("gruppoinfo", AccessLevel.Player, new CommandEventHandler(GruppoBase.GruppoInfo_OnCommand));
            CommandSystem.Register("c", AccessLevel.Player, new CommandEventHandler(GruppoBase.GruppoChat_OnCommand));
            CommandSystem.Register("gruppa", AccessLevel.Player, new CommandEventHandler(GruppoDiCaccia.Gruppa_OnCommand));
        }

        private static void GruppoInfo_OnCommand(CommandEventArgs e)
        {
            PlayerMobile player = (PlayerMobile)e.Mobile;
            if (player.Gruppo == null)
            {
                player.SendMessage("Non fai parte di un gruppo!");
                return;
            }

            e.Mobile.SendGump(new GruppoInfoGump(player));
        }

        private static void GruppoChat_OnCommand(CommandEventArgs e)
        {
            PlayerMobile player = (PlayerMobile)e.Mobile;

            if (player.Gruppo == null)
                return;

            foreach (PlayerMobile p in player.Gruppo.Partecipanti)
            {
                p.SendMessage(player.Name + ": " + e.ArgString);
            }
        }


        public List<PlayerMobile> Partecipanti { get { return m_Partecipanti; } }
        public int maxPartecipanti { get { return m_maxPartecipanti; } }
        public int numPartecipanti 
        {
            get
            {
                return m_numPartecipanti;
            }

            set
            {
                m_numPartecipanti = value;
            }
        }
        public PlayerMobile Fondatore {
            get 
            { 
                return m_Fondatore; 
            }

            set 
            { 
                m_Fondatore = value;
            }
        }

        [Constructable]
        public GruppoBase(PlayerMobile fondatore)
        {
            m_Partecipanti = new List<PlayerMobile>();
            Partecipanti.Add(fondatore);
            numPartecipanti = 1;
            Fondatore = fondatore;
        }

        // La media dei livelli dei partecipanti.
        public virtual int Livello
        {
            get
            {
                int somma = 0;
                foreach (PlayerMobile p in Partecipanti)
                {
                    somma += p.Livello;
                }

                return (int)Math.Round( somma / (double)numPartecipanti );           
            }
        }

        // Il livello del PG piu alto
        public virtual int MaxLivello
        {
            get
            {
                int max = 0;
                foreach (PlayerMobile p in Partecipanti)
                {
                    if (p.Livello > max)
                        max = p.Livello;
                }

                return max;
            }
        }

        // Somma dei livelli dei partecipanti
        public virtual int SommaLivelli
        {
            get
            {
                int somma = 0;
                foreach (PlayerMobile p in Partecipanti)
                {
                    somma += p.Livello;
                }

                return somma;
            }
        }
        

        public virtual bool AggiungiPartecipante(PlayerMobile player)
        {
            // Gruppo pieno
            if (m_numPartecipanti == m_maxPartecipanti)
            {
                player.SendMessage("Il gruppo e' pieno.");
                return false;
            }

            // Il player fa gia' parte di un gruppo
            if (player.Gruppo != null)
            {
                return false;
            }

            foreach (PlayerMobile p in Partecipanti)
            {
                p.SendMessage("{0} entra a far parte del gruppo.", player.Name);
            }

            Partecipanti.Add(player);
            player.Gruppo = this;
            numPartecipanti++;

            player.SendMessage("Fai ora parte del gruppo");

            return true;
        }

        public virtual bool RimuoviPartecipante(PlayerMobile player)
        {
            player.Gruppo = null;

            // Il gruppo e' gia vuoto!
            if (m_numPartecipanti == 0)
            {    
                return false;
            }

            // Il player non fa parte di questo gruppo
            if (!Appartenente(player))
            {
                return false;
            }

            Partecipanti.Remove(player);
            numPartecipanti--;

            foreach (PlayerMobile p in Partecipanti)
            {
                p.SendMessage("{0} e' uscito dal gruppo.", player.Name);
            }

            player.SendMessage("Sei uscito dal gruppo");

            return true;
        }

        public bool Appartenente(PlayerMobile player)
        {
            foreach (PlayerMobile p in Partecipanti)
            {
                if (player == p)
                    return true;
            }

            return false;
        }

        public void Disperdi()
        {
            Fondatore.PublicOverheadMessage(MessageType.Regular, 0x3B2, false, "Dichiaro sciolta la compagnia!");

            foreach (PlayerMobile p in Partecipanti)
            {
                p.Gruppo = null;
                p.SendMessage("Il gruppo a cui appartenevi e' stato sciolto.");
            }

            Partecipanti.Clear();
        }

        public void MandaMessaggioAlGruppo(PlayerMobile mittente, String messaggio)
        {
            foreach (PlayerMobile p in Partecipanti)
            {
                if (p == mittente)
                    continue;

                p.SendMessage(messaggio);
            }
        }

        //public void MandaMessaggioAlGruppo(PlayerMobile mittente, String messaggio, int hue)
        //{
        //    MandaMessaggioAlGruppo(PlayerMobile mittente, String messaggio);
        //}
    }

    public class GruppaPlayerTarget : Target
    {
        public GruppaPlayerTarget()
            : base(15, false, TargetFlags.None)
        {
        }

        protected override void OnTarget(Mobile from, object targeted)
        {
            if ( ! (targeted is PlayerMobile) )
                return;

            PlayerMobile Richiedente = (PlayerMobile)from;
            PlayerMobile Destinatario = (PlayerMobile)targeted;

            if (Richiedente.Gruppo == null)
                return;

            if (Richiedente.Gruppo.Appartenente(Destinatario))
            {
                Richiedente.SendMessage("Il PG fa gia' parte di questo gruppo.");
                return;
            }

            if (Destinatario.Gruppo != null)
            {
                Richiedente.SendMessage("Il PG fa gia' parte di un gruppo.");
                return;
            }
           
            Destinatario.SendGump(new RichiestaGruppoGump(Richiedente, Destinatario));
        }
    }

    public class GruppoDiCaccia : GruppoBase
    {
        private int m_LivelloGruppo; // livello del PG piu alto
        const int m_MaxDifferenzaDiLivello = 8; // La massima differenza di livello tra PG del gruppo

        public int MaxDifferenzaDiLivello { get { return m_MaxDifferenzaDiLivello; } }
        public int LivelloGruppo
        {
            get
            {
                return m_LivelloGruppo;
            }

            set
            {
                m_LivelloGruppo = value;
            }
        }

        [Constructable]
        public GruppoDiCaccia(PlayerMobile fondatore) : base(fondatore)
        {
            LivelloGruppo = fondatore.Livello;
        }

        public override bool AggiungiPartecipante(PlayerMobile player)
        {
            foreach (PlayerMobile p in Partecipanti)
            {
                if (Math.Abs(player.Livello - p.Livello) > MaxDifferenzaDiLivello)
                {
                    player.SendMessage("Il tuo livello non e' conforme a questo gruppo.");
                    return false;
                }
            }

            return base.AggiungiPartecipante(player);
        }

        public static void Gruppa_OnCommand(CommandEventArgs e)
        {
            if (! (e.Mobile is PlayerMobile) )
            {
                return;
            }

            PlayerMobile player = (PlayerMobile)e.Mobile;

            // Il player non fa parte di un gruppo, ne creiamo uno nuovo
            if (player.Gruppo == null)
            {
                // Creazione de gruppo
                player.Gruppo = new GruppoDiCaccia(player);
                e.Mobile.SendGump(new GruppoInfoGump(player));
            }

            player.Target = new GruppaPlayerTarget();            
        }
    }
}
